﻿namespace WebCamera
{
    using mshtml;
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.IO;
    using System.Runtime.CompilerServices;
    using System.Text;

    public class IEPage : IBrowserPage
    {
        private IHTMLElement _body;
        private WebCamera.BrowserWindow _BrowserWindow;
        private IHTMLDocument2 _doc;
        private List<string> _files;
        private IntPtr _Handle;
        private Guid _ID;
        private List<Point> _points;
        private static readonly int STRING_LENGTH = 0x100;

        private IEPage()
        {
        }

        public IEPage(IntPtr handle, WebCamera.BrowserWindow win)
        {
            this._ID = Guid.NewGuid();
            this._Handle = handle;
            this._files = new List<string>();
            this._points = new List<Point>();
            this._BrowserWindow = win;
            this._doc = (IHTMLDocument2)this.GetMsHTMLComponent(handle);
            if (this.IsDTDDocument(this._doc))
            {
                this._body = ((IHTMLDocument3)this._doc).documentElement;
            }
            else
            {
                this._body = this._doc.body;
            }
            if (win.FocusControlHandle != IntPtr.Zero)
            {
                OSSupport.RECT rect;
                OSSupport.RECT rect2;
                OSSupport.GetWindowRect(this._Handle, out rect);
                OSSupport.GetWindowRect(win.FocusControlHandle, out rect2);
                try
                {
                    Bitmap image = new Bitmap(rect2.Right - rect2.Left, rect2.Bottom - rect2.Top, PixelFormat.Format16bppRgb555);
                    Graphics graphics = Graphics.FromImage(image);
                    IntPtr hdc = graphics.GetHdc();
                    OSSupport.PrintWindow(win.FocusControlHandle, hdc, 0);
                    //Console.WriteLine("focus hwnd" + this.BrowserWindow.FocusControlHandle);
                    graphics.ReleaseHdc(hdc);
                    graphics.Flush();
                    string str = string.Concat(new object[] { this._ID, "-", this._files.Count.ToString(), ".tmp" });
                    str = Path.Combine(Configration.SavePath, str);
                    image.Save(str);
                    this._files.Add(str);
                    this._points.Add(new Point(rect2.Left, rect2.Top - rect.Top));
                }
                catch (Exception exception)
                {
                    Log.Write(exception);
                    throw new PCException();
                }
            }
        }

        public void CombineImage(string file)
        {
            Bitmap bitmap = new Bitmap(this.Width, this.Height, PixelFormat.Format16bppRgb555);
            Graphics graphics = Graphics.FromImage(bitmap);
            for (int i = this._files.Count - 1; i >= 0; i--)
            {
                Image image = Image.FromFile(this._files[i]);
                graphics.DrawImage(image, this._points[i]);
                image.Dispose();
                System.IO.File.Delete(_files[i]);
            }
            bitmap.Save(file);
        }

        private object GetMsHTMLComponent(IntPtr hwnd)
        {
            if (hwnd == IntPtr.Zero)
            {
                return null;
            }
            object objectValue = RuntimeHelpers.GetObjectValue(new object());
            Guid riid = new Guid("3050F80C-98B5-11CF-BB82-00AA00BDCE0B");
            string lpString = "WM_HTML_GETOBJECT";
            int msg = OSSupport.RegisterWindowMessage(lpString);
            if (msg == 0)
            {
                throw new PageReferenceException();
            }
            if (OSSupport.ObjectFromLresult(OSSupport.SendMessage(hwnd, msg, IntPtr.Zero, IntPtr.Zero), ref riid, IntPtr.Zero, ref objectValue) != 0)
            {
                //Log.Write("Unable to get IE DOM from window message result");
                throw new PageReferenceException();
            }
            return objectValue;
        }

        public static List<IntPtr> GetPageHandlers(IntPtr window)
        {
            //Console.WriteLine("win handler:" + window.ToString());
            List<IntPtr> list = new List<IntPtr>();
            StringBuilder lpString = new StringBuilder(STRING_LENGTH);
            if (IntPtr.Zero != window)
            {
                IntPtr hWnd = OSSupport.GetWindow(window, 5);
                StringBuilder s = new StringBuilder(STRING_LENGTH);
                try
                {
                    while (IntPtr.Zero != hWnd)
                    {
                        IntPtr ptr3;
                        OSSupport.GetClassName(hWnd.ToInt32(), s, STRING_LENGTH);

                        //IE8 added 2009/11/17
                        if (s.ToString().Contains("Frame Tab"))
                        {
                            StringBuilder builder3 = new StringBuilder(STRING_LENGTH);
                            for (IntPtr ptr2 = OSSupport.GetWindow(hWnd, 5); IntPtr.Zero != ptr2; ptr2 = OSSupport.GetWindow(ptr2, 2))
                            {
                                OSSupport.GetClassName(ptr2.ToInt32(), builder3, STRING_LENGTH);
                                if (builder3.ToString().Contains("TabWindowClass"))
                                {
                                    StringBuilder builder4 = new StringBuilder(STRING_LENGTH);
                                    for (IntPtr ptr4 = OSSupport.GetWindow(ptr2, 5); IntPtr.Zero != ptr4; ptr4 = OSSupport.GetWindow(ptr4, 2))
                                    {
                                        OSSupport.GetClassName(ptr4.ToInt32(), builder4, STRING_LENGTH);
                                        if (builder4.ToString().Contains("Shell DocObject View"))
                                        {
                                            ptr3 = OSSupport.FindWindowEx(ptr4, IntPtr.Zero, "Internet Explorer_Server", IntPtr.Zero);
                                            OSSupport.GetWindowText(hWnd, lpString, STRING_LENGTH);
                                            list.Add(ptr3);
                                        }
                                    }
                                }
                            }
                        }
                        // end 2009/11/17 

                        //IE7
                        if (s.ToString().Contains("TabWindowClass"))
                        {
                            StringBuilder builder3 = new StringBuilder(STRING_LENGTH);
                            for (IntPtr ptr2 = OSSupport.GetWindow(hWnd, 5); IntPtr.Zero != ptr2; ptr2 = OSSupport.GetWindow(ptr2, 2))
                            {
                                OSSupport.GetClassName(ptr2.ToInt32(), builder3, STRING_LENGTH);
                                if (builder3.ToString().Contains("Shell DocObject View"))
                                {
                                    ptr3 = OSSupport.FindWindowEx(ptr2, IntPtr.Zero, "Internet Explorer_Server", IntPtr.Zero);
                                    OSSupport.GetWindowText(hWnd, lpString, STRING_LENGTH);
                                    list.Add(ptr3);
                                }
                            }
                        }
                        else if (s.ToString().Contains("Shell DocObject View"))
                        {
                            ptr3 = OSSupport.FindWindowEx(hWnd, IntPtr.Zero, "Internet Explorer_Server", IntPtr.Zero);
                            OSSupport.GetWindowText(hWnd, lpString, STRING_LENGTH);
                            list.Add(ptr3);
                        }
                        hWnd = OSSupport.GetWindow(hWnd, 2);
                    }
                }
                catch (Exception exception)
                {
                    Log.Write(exception);
                }
            }
            return list;
        }

        private bool IsDTDDocument(object document)
        {
            IHTMLDocument3 document2 = (IHTMLDocument3)document;
            IHTMLDOMChildrenCollection childNodes = (IHTMLDOMChildrenCollection)document2.childNodes;
            IHTMLDOMNode node = (IHTMLDOMNode)childNodes.item(0);
            return (node.nodeValue.ToString().Contains("-//W3C//DTD") && node.nodeValue.ToString().Contains("www.w3.org"));
        }

        public string PrintWindow()
        {
            string str;
            try
            {
                Bitmap image = new Bitmap(this.ScreenWidth, this.ScreenHeight, PixelFormat.Format16bppRgb555);
                Graphics graphics = Graphics.FromImage(image);
                IntPtr hdc = graphics.GetHdc();
                OSSupport.PrintWindow(this.Handle, hdc, 0);
                //Console.WriteLine("focus hwnd" + this.BrowserWindow.FocusControlHandle);
                graphics.ReleaseHdc(hdc);
                graphics.Flush();
                str = string.Concat(new object[] { this._ID, "-", this._files.Count.ToString(), ".tmp" });
                str = Path.Combine(Configration.SavePath, str);
                image.Save(str);
                this._files.Add(str);
                this._points.Add(new Point(this.X, this.Y));
            }
            catch (Exception exception)
            {
                Log.Write(exception);
                throw new FileCanNotSaveException();
            }
            return str;
        }

        public void ScrollTo(int x, int y)
        {
            try
            {
                this._body.setAttribute("scrollLeft", x, 0);
                this._body.setAttribute("scrollTop", y, 0);
            }
            catch (Exception exception)
            {
                Log.Write(exception);
                throw new ScrollException();
            }
        }

        public WebCamera.BrowserWindow BrowserWindow
        {
            get
            {
                if (this._BrowserWindow == null)
                {
                    throw new BWReferenceException();
                }
                return this._BrowserWindow;
            }
        }

        public IntPtr Handle
        {
            get
            {
                return this._Handle;
            }
        }

        public int Height
        {
            get
            {
                return (int)this._body.getAttribute("scrollHeight", 0);
            }
        }

        public Guid ID
        {
            get
            {
                return this._ID;
            }
        }

        public bool IsDownloadCompleted
        {
            get
            {
                return this._doc.readyState.Equals("complete");
            }
        }

        public int ScreenHeight
        {
            get
            {
                return (int)this._body.getAttribute("clientHeight", 0);
            }
        }

        public int ScreenWidth
        {
            get
            {
                return (int)this._body.getAttribute("clientWidth", 0);
            }
        }

        public string Url
        {
            get
            {
                return this._doc.url;
            }
        }

        public bool Visible
        {
            get
            {
                return OSSupport.IsWindowVisible(this._BrowserWindow.Handle);
            }
            set
            {
                try
                {
                    if (value)
                    {
                        OSSupport.ShowWindow(this._BrowserWindow.Handle, 5);
                    }
                    else
                    {
                        OSSupport.ShowWindow(this._BrowserWindow.Handle, 0);
                    }
                }
                catch (Exception exception)
                {
                    Log.Write(exception);
                    throw new CaptureException();
                }
            }
        }

        public int Width
        {
            get
            {
                return (int)this._body.getAttribute("scrollWidth", 0);
            }
        }

        public int X
        {
            get
            {
                return (int)this._body.getAttribute("scrollLeft", 0);
            }
            set
            {
                this._body.setAttribute("scrollLeft", value, 0);
            }
        }

        public int Y
        {
            get
            {
                return (int)this._body.getAttribute("scrollTop", 0);
            }
            set
            {
                this._body.setAttribute("scrollTop", value, 0);
            }
        }
    }
}

